Коммуникационный протокол (далее просто "протокол") использует в своей работе три сущности:
1) Команда (Command);
2) Сообщение (Message);
3) Контент сообщения (Content).

-- Команда --
Команда это 128-ми битный идентификатор (uuid), который идентифицирует выполняемое действие. Условно команду можно охарактеризовать следующими состояниями:
  Command - непосредственно прямая команда на выполнение действия;
  Ansver  - ответ (или результат) выполнения команды с типом Command;
  Event   - данный тип команды похож на Command, но не предполагает получения ответа (Answer).
            Он используется для рассылки широковещательных сообщений о событиях.

Примеры команд:
QUuidEx Unknown = "4aef29d6-5b1a-4323-8655-ef0d4f1bb79d"; // Идентификатор неизвестной команды
QUuidEx Error   = "b18b98cc-b026-4bfe-8e33-e7afebfbe78b"; // Идентификатор сообщения об ошибке


-- Базовые команды --
Существует минимальный набор команд, которые должны поддерживаться приложением. 

/**
  Идентификатор неизвестной команды
*/
QUuidEx Unknown = "4aef29d6-5b1a-4323-8655-ef0d4f1bb79d"

/**
  Идентификатор сообщения об ошибке
*/
QUuidEx Error = "b18b98cc-b026-4bfe-8e33-e7afebfbe78b"

/**
  Запрос информации о совместимости. При подключении клиент и сервер отправляют
  друг другу информацию о совместимости
*/
QUuidEx ProtocolCompatible = "173cbbeb-1d81-4e01-bf3c-5d06f9c878c3"

/**
  Требование закрыть TCP-соединение. Эта команда работает следующим образом:
  сторона, которая хочет закрыть соединение отправляет это сообщение с инфор-
  мацией о причине необходимости закрыть соединение.  Принимающая  сторона
  записывает эту информацию в свой лог (или использует иным образом), затем
  отправляет обратное пустое сообщение.  После того,  как ответное сообщение
  получено - TCP-соединение может быть разорвано. Такое поведение реализовано
  для того чтобы сторона с которой разрывают соединение  имела  информацию о
  причине разрыва
*/
QUuidEx CloseConnection = "e71921fd-e5b3-4f9b-8be7-283e8bb2a531"

Определение базовых команд находится в файле commands_base.h
https://github.com/hkarel/SharedTools/blob/master/qt/communication/commands_base.h

-- Сообщение --
Сообщение можно представить как некий контейнер использующийся для пересылки команды совместно с данными необходимыми для выполнения этой команды. Для json-варианта сообщения приведены наиболее значимые поля:
id          - персональный идентификатор сообщения (uuid);
command     - идентификатор команды (uuid);
flags       - поле битовых флагов, хранит состояние и статусы передаваемого сообщения;
type        - тип пересылаемой команды: command, ansver, event (содержится внутри поля flags);
execStatus  - статус выполнения/обработки команды (содержится внутри поля flags);
priority    - приоритет сообщения (содержится внутри поля flags);
maxTimeLife - максимальное время жизни сообщения (используется для реализации синхронных вызовов);
content     - контент сообщения (полезная нагрузка, сериализованные данные);
tags        - содержит список 8-ми байтовых (uint64) значений. Максимальная длина списка 255 элементов.
              Назначение списка: хранение произвольных пользовательских данных без сериализации их поле content.

Побитовое описание поля flags (4 байта, 32 бита):
    --- Байт 1 ---
    Тип пересылаемого сообщения, соответствует enum Message::Type (занимает 3 бита)
    quint32 type: 3;

    Статус выполнения команды, соответствует enum Message::ExecStatus (занимает 3 бита)
    quint32 execStatus: 3;

    Приоритет сообщения, соответствует enum Message::Priority (занимает 2 бита)
    quint32 priority: 2;

    --- Байт 2 ---
    Параметр определяет два признака:
    1) Контент сжат/не сжат;
    2) Алгоритм сжатия.
    Параметр соответствует enum Message::Compression (занимает 3 бита)
    quint32 compression: 3;

    Признаки пустых полей. Признаки используются для оптимизации размера сообщения
    при его сериализации
    quint32 tagsIsEmpty: 1;
    quint32 maxTimeLifeIsEmpty: 1;
    quint32 contentIsEmpty: 1;

    quint32 reserved2: 2;

    --- Байт 3 ---
    quint32 reserved3: 8;

    --- Байт 4 ---
    Формат сериализации контента, соответствует enum SerializationFormat (занимает 3 бита)
    quint32 contentFormat: 3;
    quint32 reserved4: 4;

    Признак пустого флага _flags2.  Признак используется  для  оптимизации
    размера сообщения при его сериализации.  Данный признак идет последним
    битом в поле _flags
    quint32 flags2IsEmpty: 1;


Полное описание полей сообщения содержится в файле message.h
https://github.com/hkarel/SharedTools/blob/master/qt/communication/message.h

Пример записи сообщения в json-представлении:
{
    "id":"3caca371-bab1-4758-98db-e1251e49d45f",
    "command":"2ec05fe5-366a-41c9-a283-5a617767738d",
    "flags":2164267082,
    "content":{"users":["user1","user2","user3"]}
}


-- Контент сообщения --
Контент - это данные (полезная нагрузка) передаваемые с конкретной командой. Контент может передаваться с любым типом сообщения (Command, Ansver, Event). В контексте языка С++ контент описывается с помощью структуры данных (struct). Для того чтобы установить ассоциативную связь между командой и контентом сообщения (структурой данных) используется механизм наследования от базового класса Data. Так, описание контента сообщения для команды CloseConnection будет выглядеть следующим образом:

struct CloseConnection : Data<&command::CloseConnection,
                               Message::Type::Command>
{
    qint32  code = {0};   // Код причины. Нулевой код соответствует
                          // несовместимости версий протоколов.
    QString description;  // Описание причины закрытия соединения
};

В этом примере со структурой CloseConnection ассоциируется команда command::CloseConnection, а так же структуре назначается атрибут Message::Type::Command. Это означает, что данная структура может быть использована в качестве контента только в сообщениях с типом Command, но не может быть использована в сообщении с типами Ansver и Event.


-- Обработка ошибок --
Для информировании об ошибочной ситуации существует команда Error.

QUuidEx Error = "b18b98cc-b026-4bfe-8e33-e7afebfbe78b"

Контент для команды Error выглядит следующим образом:

struct Error : Data<&command::Error,
                     Message::Type::Command>
{
    QUuidEx commandId;   // Идентификатор команды
    QUuidEx messageId;   // Идентификатор сообщения
    qint32  group = {0}; // Используется для группировки сообщений по группам
    QUuidEx code;        // Глобальный код ошибки
    QString description; // Описание ошибки
};

Но наиболее часто для обработки ошибок используется другой механизм: возврат информации об ошибке в сообщении с типом Message::Type::Answer. Для этой цели определены две структуры:

struct MessageError
{
    qint32  group = {0};  // Используется для группировки сообщений по группам
    QUuidEx code;         // Глобальный код ошибки
    QString description;  // Описание ошибки
};

struct MessageFailed
{
    qint32  group = {0};  // Используется для группировки сообщений по группам
    QUuidEx code;         // Глобальный код неудачи
    QString description;  // Описание неудачи
};

Структура MessageError предназначена для описания ошибки при выполнении команды. Структура MessageFailed используется в том случае, когда выполнение команды не завершилось ошибкой, но и успешного результата тоже нет.
У сообщения есть специальное поле - execStatus, оно описывает результат выполнения операции. Поле execStatus имеет смысл только для сообщений с типом Message::Type::Answer, в остальных случаях оно имеет неопределенное состояние. Поле execStatus может принимать следующие значения:

Unknown = 0 - Неопределенное состояние.
Success = 1 - Сообщение было обработано успешно и содержит корректные
              ответные данные.
Failed  = 2 - Сообщение не было обработано, но результат выполнения не является успешным,
              но и не является ошибкой. В данном случае сообщение будет содержать данные
              в формате MessageFailed.
Error   = 3 - При обработке сообщения произошла ошибка. В качестве ответа отправляется
              сообщения с описанием причины ошибки.
              В данном случае сообщение будет содержать данные в формате MessageError.


Пример записи сообщения с параметром execStatus = Error в json-представлении:
{
    "id":"7a411ec0-ef09-4bde-a5a5-bc8c709c631d",
    "command":"fc7f12a8-9643-4e81-9d27-53b99c19d319",
    "flags":2164267090,
    "content":{group:0,"code":"d9a76e6e-c8a1-4217-b8e1-0f7262ecebca","description":"Failed user authorization"}
}


-- Порядок установки соединения --
После установки TCP соединения клиент отправляет на сокет сервера 16 байт (обычный uuid). Это сигнатура протокола. Строковое представление сигнатуры для json формата: "fea6b958-dafb-4f5c-b620-fe0aafbd47e2". Если сервер присылает назад этот же uuid, то все ОК - можно работать, иначе TCP соединение разрывается. Сервер ожидает получения сигнатуры протокола в течении 3-х секунд, клиент ожидает ответа от сервера 6 секунд. Если в течении указанного времени сигнатуры не будут получены - TCP соединение будет разорвано.
После того как сигнатуры протокола проверены клиент и сервер отправляют друг другу первое сообщение - ProtocolCompatible. Это сообщение помимо проверки версий протокола запускает очередь обработки сообщений, если это сообщение не будет отправлено механизм не сможет корректно работать, никакие другие сообщения кроме CloseConnection не будут обрабатываться.


-- Порядок передачи коммуникационных пакетов через TCP сокет --
Как было описано ранее сразу после установки TCP соединения клиент и сервер обмениваются сигнатурами протокола (пакеты фиксированной длины в 16 байт). Далее сокеты обмениваются коммуникационными пакетами в следующем формате:
- поле 1: 4 байта содержат размер пакета (поле соответствует типу integer);
- поле 2: пакет данных длиной указанной в поле 1.

Примечания:
1) Размер пакета в поле 1 записывается в сетевом представлении (порядок байт  big-endian)
2) Если размер пакета меньше нуля, это означает, что пакет сжат с использованием zip-алгоритма. В этом случае размер пакета равен (поле 1) * -1. После чтения пакета из буфера сокета нужно провести его декомпрессию.
3) Механизм сжатия (п.2) может быть отключен по согласованию взаимодействующих сторон.
